package com.wondertek.poms.pre.manager;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.wondertek.poms.common.constant.Constants;
import com.wondertek.poms.common.exception.MessageCodes;
import com.wondertek.poms.core.service.ISyncTaskService;
import com.wondertek.poms.dao.po.Content;
import com.wondertek.poms.dao.po.SyncTask;
import com.wondertek.poms.pre.config.RedisDistributedLockOut;
import com.wondertek.poms.pre.manager.imageback.RulePassProcess;
import com.wondertek.poms.pre.manager.move.MoveNasFileManager;
import com.wondertek.poms.pre.manager.xml2Cont.Xml2ContentManager;
import com.wondertek.poms.pre.message.BusinessException;
import com.wondertek.poms.pre.rabbitmq.pojo.MessagePojo;
import com.wondertek.poms.pre.rabbitmq.provider.MessageProvider;
import com.wondertek.poms.pre.utils.callback.SourceUtil;
import com.wondertek.poms.transform.xmlvo.SyncRequest;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class StartProcess {
    @Autowired
    private RedisDistributedLockOut lock;
    // poms同步请求开关
    @Value(value = "${syncpre.poms.sync.on.off:on}")
    public String syncOnOff;
    // redis延迟队列时间（分钟）
    @Value(value = "${syncpre.poms.delay.time:5}")
    public Integer delayTime;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    Xml2ContentManager xml2ContentManager;
    @Autowired
    MoveNasFileManager moveNasFileManager;
    @Autowired
    private ISyncTaskService syncTaskService;
    @Autowired
    SourceUtil sourceUtil;
    /**rabbitMq 生产者*/
    @Autowired
    private MessageProvider messageProvider;
    @Autowired
    RulePassProcess rulePassProcess;

    @Async(value = "fastPool")
    public void fastProcess(String message) {
    	log.info("内容同步主流程|mq消息：" + message);
        SyncRequest st = JSONUtil.toBean(message, SyncRequest.class);
        process(st, true);
    }

    @Async(value = "slowPool")
    public void slowProcess(String message) {
    	log.info("内容同步主流程|延时队列mq消息：" + message);
        SyncRequest st = JSONUtil.toBean(message, SyncRequest.class);
        process(st, false);
    }

    public void process(SyncRequest syr, boolean isFast) {
        String requestId = lock.getRequestId();
        log.info("内容同步主流程|assetId:{}|contentId:{}|requestId:{}|尝试获取分布式锁",
                syr.getAccessID(), syr.getSvcCont().getContentID(), requestId);
        if (lock.lockRetry(Constants.SYNC_LOCK_PREFIX + syr.getAssetId(), requestId)) {
            boolean isSuccess = true;
            SyncTask st = null;
            try {
            	// 1.入库syncTask 任务
            	st = insertDB(syr);
                mainProcess(syr, st);
            } catch (Exception e) {
                log.error(syr.getSvcCont().getContentID() + "内容同步主流程|处理异常：", e);
                isSuccess = false;
                
                if (st != null) {
                    st.setStatus(3);
                    syncTaskService.save(st);
                }
            } finally {
                callback(syr, isSuccess, requestId);
                // 把requestId存入reids，用于poms同步解锁;
                redisTemplate.opsForValue().set(Constants.SYNC_LOCK_REQUESTID + syr.getAssetId(), requestId,
                        RedisDistributedLockOut.EXPIRE, TimeUnit.MILLISECONDS);
            }
        } else {
        	// 拿不到锁进入延时队列
			MessagePojo msg = new MessagePojo(delayTime * 60, null, JSONUtil.toJsonStr(syr));
            messageProvider.sendMessage(msg);
            log.error("内容同步主流程|accessId:{},contentId:{}|获取锁失败，此节目正在执行，任务进入延迟队列", syr.getAssetId(), syr.getSvcCont().getContentID());
        }
    }

    private void callback(SyncRequest st, boolean success, String requestId) {
        log.info("内容同步主流程|业务数据：" + st.getSvcCont().getContentID() + "|媒资id：" + st.getAssetId() + "同步是否成功：" + success);
		if (!success) {
			// 解除分布式锁
			lock.unLock(Constants.SYNC_LOCK_PREFIX + st.getAssetId(), requestId);
			if (StrUtil.isNotBlank(st.getMd5Key())) {
				redisTemplate.delete(st.getMd5Key()); // 清除redis中的数据，结束业务
			}
			sourceUtil.pomsResponse(st, success);
		}
    }

    /**
     * <p><b>Title:</b> mainProcess</p>
     * <p><b>Description:</b> 主业务入口</p>
     *
     * @param syr
     * @throws JsonProcessingException
     * @author douzi
     * @throws Exception 
     */
    SyncTask mainProcess(SyncRequest syr, SyncTask st) throws Exception {
		// 2.解析 nas上媒资xml、
    	Content c = xml2ContentManager.process(st);
    	if (c == null) {
    		throw new BusinessException(MessageCodes.M970807);
    	}
    	
    	if (st.getOprCode().equals(Constants.SYNC_POMS_OPRCODE_CONTENT_DELETE)) {
    		// 3.如果是内容删除，不需要处理内容对象，xml，nas搬迁等业务；直接准备下线
    		rulePassProcess.process(st);
        } else {
        	// 3.copy原始文件到poms nas、发送转图任务
        	moveNasFileManager.process(st, c);
        }
    	return st;
    }
    
    /**
     * SyncRequest转化SyncTask 并入库
     *
     * @param syr
     * @return
     */
    public SyncTask insertDB(SyncRequest syr) {
        SyncTask st = new SyncTask();
        st.setAccessId(syr.getAccessID());
        st.setAccessPlatformId(syr.getAccessPlatformID());
        st.setAccessPlatformType(syr.getAccessPlatformType());
        st.setAccessPwd(syr.getAccessPwd());
        st.setAccessSeq(syr.getAccessSeq());
        st.setBasePath(syr.getSvcCont().getBasePath());
        st.setContentId(syr.getSvcCont().getContentID());
        st.setCpId(syr.getSvcCont().getCpId());
        st.setDistResult(syr.getSvcCont().getDistResult());
        st.setNeedBc(syr.getSvcCont().getNeedBC());
        st.setOprCode(syr.getSvcCont().getOprCode());
        st.setOprTime(syr.getSvcCont().getOprTime());
        st.setPriority(syr.getSvcCont().getPriority());
        st.setServType(syr.getSvcCont().getServType());
        st.setUpdateFields(syr.getSvcCont().getUpdateFields());
        st.setVersion(syr.getVersion());
        st.setAssetId(syr.getAssetId());
        st.setSyncTime(java.time.LocalDateTime.now());
        st.setStatus(1);
        syncTaskService.save(st);
        log.info("内容同步主流程|业务数据：" + syr.getSvcCont().getContentID() + 
        		"|媒资id：" + syr.getAccessID() + "|保存同步任务对象成功");
        return st;
    }
}
